package admin

import (
	"context"
	"fmt"
	"github.com/zeromicro/go-zero/core/logx"
	"gozero-demo/internal/constants"
	"gozero-demo/internal/repo/mysql"
	"gozero-demo/internal/svc"
	"gozero-demo/internal/svc/debugx"
	"gozero-demo/internal/types"
)

type UpdateUserStatusLogic struct {
	logx.Logger
	ctx      context.Context
	svcCtx   *svc.ServiceContext
	userRepo *mysql.UserRepo
}

// 更新用户状态
func NewUpdateUserStatusLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateUserStatusLogic {
	return &UpdateUserStatusLogic{
		Logger:   logx.WithContext(ctx),
		ctx:      ctx,
		svcCtx:   svcCtx,
		userRepo: mysql.NewUserRepo(ctx, svcCtx),
	}
}

func (l *UpdateUserStatusLogic) UpdateUserStatus(req *types.UpdateUserStatusRequest) (resp *types.CommonResponse, err error) {
	//校验当前数据是否存在
	existInfo, err := l.userRepo.GetUserInfo(req.Id)
	if err != nil {
		return nil, err
	}
	if existInfo == nil {
		return nil, constants.UserDataNotFound
	}

	// 事务处理tx
	txCtx := l.ctx
	tx := l.svcCtx.Model.Begin()
	if tx.Error != nil {
		logx.WithContext(txCtx).Errorf("Failed to start transaction: %v", tx.Error)
		debugx.PrintStack()
		txErr := *constants.TransactionStartFail
		txErr.Msg = fmt.Sprintf("%v: %v", txErr.Msg, tx.Error.Error())
		return nil, &txErr
	}
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
			logx.WithContext(txCtx).Errorf("Panic occurred, rolling back transaction: %v", r)
			debugx.PrintStack()

			txErr := *constants.PanicOccurred
			txErr.Msg = fmt.Sprintf("%v: %v", txErr.Msg, r)
			err = &txErr
		} else if err != nil {
			tx.Rollback()
			logx.WithContext(txCtx).Errorf("Error occurred, rolling back transaction: %v", err)
			if _, ok := err.(*types.MyError); !ok {
				debugx.PrintStack() //如果不是自定义的error,则打印堆栈信息
			}
		} else {
			tx.Commit()
			logx.WithContext(txCtx).Infof("Transaction committed successfully")
		}
	}()

	//更新数据
	updateFields := map[string]interface{}{
		"status": req.Status,
	}
	_, err = l.userRepo.UpdateUserV2(updateFields, req.Id, tx)
	if err != nil {
		return nil, err
	}

	return types.SuccessResponseEmpty(l.ctx), nil
}
